"""
    2021-08-12  15:21   by  CYL & CSDN
    文件：
        main.py
        已整合至xlsxTools.py
    参考网站：
        1)https://blog.csdn.net/weixin_41546513/article/details/109555832
        2)https://openpyxl.readthedocs.io/en/stable/
        3)https://openpyxl.readthedocs.io/en/stable/styles.html
    注意：
        与xlwt,xlrd不同，
        openpyxl的cell下标和实际的.xlsx是一致的，即最左上角的单元格位置为(1,1)，而不是(0,0)。
    后续：
        删除单元格等等的操作。
"""

import openpyxl
from openpyxl.styles import PatternFill, Border, Side, Alignment, Protection, Font
import os

openpyxl_color_dict = {
    "Black":"00000000",
    "White":"00FFFFFF",
    "Red":"00FF0000",
    "Green":"0000FF00",
    "Blue":"000000FF",
    "Yellow":"00FFFF00",
    "Pink":"00FF00FF",
    "Cyan":"0000FFFF",
    "Brown":"00800000",
    "Orange":"00FF6600",
    "Gray":"00969696",
    "淡紫":"009999FF",
    "淡粉":"00FF99CC",
    "墨绿":"00008000",
    "淡橙":"00FFCC00"
}
#   注册完的样式需要去.xlsx文件中的“格式”->“样式中删除”，程序目前只能注册。
#   my_style_WR：为 红底白字居中加粗自动换行 样式表。
#   PatternFill为渐变和填充。
my_style_WR = openpyxl.styles.NamedStyle(
    name = "my_style_WR",
    font = Font(name='Microsoft YaHei UI',
                size=8,
                bold=True,
                italic=False,
                vertAlign=None,
                underline='none',
                strike=False,
                color=openpyxl_color_dict["White"]),
    fill = PatternFill(fill_type="solid",
                    start_color=openpyxl_color_dict["Red"],
                    end_color='FF000000'),
    border = Border(left=Side(border_style=None,
                                color='FF000000'),
                    right=Side(border_style=None,
                                color='FF000000'),
                        top=Side(border_style=None,
                                color='FF000000'),
                 bottom=Side(border_style=None,
                             color='FF000000'),
                 diagonal=Side(border_style=None,
                               color='FF000000'),
                 diagonal_direction=0,
                 outline=Side(border_style=None,
                              color='FF000000'),
                 vertical=Side(border_style=None,
                               color='FF000000'),
                 horizontal=Side(border_style=None,
                                color='FF000000')
                ),
    alignment=Alignment(horizontal='center',
                     vertical='center',
                     text_rotation=0,
                     wrap_text=True,
                     shrink_to_fit=False,
                     indent=0),
    number_format = 'General',
    protection = Protection(locked=True,
                         hidden=False)
)

def new_xlsx_File(sheetName:str="Sheet1",new_xlsx_file_Path:str="./newXLSXfile_byPython.xlsx")->openpyxl.workbook.workbook.Workbook:
    """
        2021-08-12  15:20   by  CYL
        函数说明：
            用于生成一个新的空白.xlsx文件。
    :param new_xlsx_file_Path:  所要生成的.xlsx的路径。
    :param sheetName:   所要生成的.xlsx的Sheet名。
    :return:    返回所生的.xlsx的book句柄
    """
    if os.path.exists(new_xlsx_file_Path):
        #os.remove(new_xlsx_file_Path)
        print(f"已存在{new_xlsx_file_Path}文件!")
    else:
        the_new_xlsx_book = openpyxl.Workbook()
        the_new_xlsx_sheet = the_new_xlsx_book.create_sheet(sheetName)
        the_new_xlsx_book.save(new_xlsx_file_Path)
        print(f"{new_xlsx_file_Path}已生成！")
        return the_new_xlsx_book

def Catch_xlsx_cell_value(Line:int,Row:int,sheetName:str,Gen_xlsx_file_Path:str)->str:
    """
        2021-08-12  15:49   by  CYL
        函数名：
            Catch_xlsx_cell_value()
        函数说明：
            用于获取某个.xlsx文件中的某个Sheet中的某个单元格上的值。
    :param Line:    单元格所在行。
    :param Row:     单元格所在列。
    :param sheetName:   单元格所在Sheet名。
    :param Gen_xlsx_file_Path:  单元格所在.xlsx文件路径。
    :return:    单元格的字符串内容。
    """
    the_xlsx_book = openpyxl.load_workbook(Gen_xlsx_file_Path)
    #   print(the_xlsx_book.sheetnames,"aim:用于显示当前xlsx中有哪些Sheet")
    the_xlsx_sheet = the_xlsx_book[sheetName]
    the_cell_value = str(the_xlsx_sheet.cell(Line,Row).value)
    print("the_cell_value = ",the_cell_value,type(the_cell_value))
    return the_cell_value

def Write_xlsx_cell_value(Line:int,Row:int,cellContent:str,sheetName:str,Gen_xlsx_file_Path:str,useNamedStyle:str=None):
    """
        2021-08-12  17:42   by  CYL
        函数名：
            Write_xlsx_cell_value()
        函数用途：
            向一个单元格中写入内容，也可以加载样式表。
    :param Line:    单元格所在的行。
    :param Row:     单元格所在的列。
    :param cellContent: 需要写入单元格中的内容。
    :param sheetName:   单元格所在的Sheet名。
    :param Gen_xlsx_file_Path:  单元格所在的.xlsx文件路径名。
    :param useNamedStyle:   单元格所需要使用的样式表。
    :return:    无。
    """
    the_xlsx_book = openpyxl.load_workbook(Gen_xlsx_file_Path)
    the_xlsx_sheet = the_xlsx_book[sheetName]
    the_xlsx_sheet.cell(Line, Row).value = cellContent
    if useNamedStyle == "my_style_WR":  #   如果使用注册样式表，样式表名：my_style_WR，即白字红底居中加粗。
        try:
            the_xlsx_book.add_named_style(my_style_WR)  #   在.xlsx中注册样式表。
        except ValueError:                              #   若样式表已存在，则会报错。
            print("my_style_WR 已存在！")
            #print(".xlsx中的样式有：",the_xlsx_book.style_names,"aim:用于显示.xlsx中已注册样式列表。")
        the_xlsx_sheet.cell(Line, Row).style = "my_style_WR"
    else:
        pass
    the_xlsx_book.save(Gen_xlsx_file_Path)

def get_xlsx_line_row_info(sheetName:str,Gen_xlsx_file_Path:str)->(int,int):
    """
        2021-08-12  17:54   by  CYL
        函数名：
            xlsx_Line_Row_info()
        函数用途：
            用于获取.xlsx的某个Sheet中的行数和列数。
    :param sheetName:   需要获取行数和列数的Sheet名。
    :param Gen_xlsx_file_Path:  需要获取行数和列数的Sheet所对应的.xlsx的路径。
    :return:    返回行数和列数，为一个元组。
    """
    the_xlsx_book = openpyxl.load_workbook(Gen_xlsx_file_Path)
    the_xlsx_sheet = the_xlsx_book[sheetName]
    print(f"{sheetName}存在{the_xlsx_sheet.max_row}行,{the_xlsx_sheet.max_column}列。")
    return (the_xlsx_sheet.max_row,the_xlsx_sheet.max_column)

def mirror_xlsx_to_new(Gen_xlsx_file_Path:str,new_xlsx_file_Path:str)->openpyxl.workbook.workbook.Workbook:
    """
        2021-08-12  18:23   by  CYL
        函数名：
            mirror_xlsx_to_new()
        函数用途：
            复制原.xlsx至新的.xlsx。
    :param Gen_xlsx_file_Path:  原.xlsx的文件路径。
    :param new_xlsx_file_Path:  新.xlsx的文件路径。
    :return:    返回新的.xlsx的book句柄。
    """
    the_xlsx_book = openpyxl.load_workbook(Gen_xlsx_file_Path)
    the_xlsx_book.save(new_xlsx_file_Path)
    return the_xlsx_book


def xlsx_demo():
    xlsx_file_Path = r"./demo0.xlsx"
    #   新建一个空白的.xlsx文件。
    new_xlsx_File()
    #   获取.xlsx文件中的最左上角单元格中的内容。
    Catch_xlsx_cell_value(1,7,"Sheet1",xlsx_file_Path)
    #   向.xlsx文件中的某个单元格中写入内容。
    Write_xlsx_cell_value(1,7,"你好世界！","Sheet1",xlsx_file_Path,useNamedStyle="my_style_WR")
    Catch_xlsx_cell_value(1, 7, "Sheet1", xlsx_file_Path)   #   用于显示之前写入的对不对。
    Write_xlsx_cell_value(1, 8, "乌拉世界！", "Sheet1", xlsx_file_Path, useNamedStyle="my_style_WR")
    #   获取某个.xlsx文件中某个Sheet中的行数和列数。
    get_xlsx_line_row_info("Sheet1",xlsx_file_Path)
    #   镜像一个.xlsx文件。
    mirror_xlsx_File_Path = r"./123.xlsx"
    mirror_xlsx_to_new(xlsx_file_Path,mirror_xlsx_File_Path)

if __name__=="__main__":
    xlsx_demo()